<template>
	<view class="input-box">
		<view class="audio" v-if="msg.length <= 0" @click="showAudio">
			<text class="iconfont icon-yuyin"></text>
			<!-- <wd-icon name="wifi" size="22px"></wd-icon> -->
			<!-- <view @click="sendMsg">发送</view> -->
		</view>
		<view v-if="isRecording" class="record-modal">
			<div class="red-mask" />
			<view class="float-element moving-slider"></view>
			<view class="float-element modal-title">
				{{ modalText }}
			</view>
		</view>
		<view @touchstart="handleTouchStart" @longpress="handleLongPress" @touchmove="handleTouchMove"
			@touchend="handleTouchEnd" class="audio-input" v-if="audioStatus">
			{{ touchBarText }}
		</view>

		<!-- 输入框组件 -->
		<view class="input" v-else>
			<wd-input custom-class="im-input-class" no-border type="text" v-model="msg" placeholder="请输入内容" />
		</view>
		<view class="upload" @click="setUploadShow">
			<wd-icon name="add-circle" size="44rpx" color="#999999" />
		</view>
		<view class="extra" v-if="msg.length > 0">
			<view @click="sendMsg">发送</view>
		</view>
	</view>
</template>

<script lang="ts" setup>
	import { ref, onMounted, defineProps, defineEmits } from "vue"
	import throttle from 'lodash/throttle';
	import { TUIGlobal } from '@tencentcloud/universal-api';
	import { useImStore, useUserStore } from '@/store';
	import { uploadFile } from "@/api/common";
	type TouchBarText = '按住说话' | '抬起发送' | '抬起取消';
	type ModalText = '正在录音' | '继续上滑可取消' | '松开手指 取消发送';
	const emits = defineEmits(['setUploadShow', 'sendMsg', 'sendAudioMsg', 'setScrollHeight']);
	const props = defineProps({
		// 是否显示语音输入按钮
		useruuid: { type: Boolean, default: null, },
	});
	const imStore = useImStore();
	const audioStatus = ref(false); // 是否显示语音输入按钮
	// 输入框信息
	const msg = ref('');

	const touchBarText = ref<TouchBarText>('按住说话');
	const modalText = ref<ModalText>('正在录音');

	let firstTouchPageY : number = -1;
	const isRecording = ref(false);
	let isManualCancelBySlide = false;
	// 录音时常
	let recordTime : number = 0;
	// 计时器
	let recordTimer : any;
	let isFingerTouchingScreen = false;
	// 师傅初始化
	let isFirstAuthrizedRecord = false;
	// 获取 recorderManager 实例
	let recorderManager : any = null;
	const recordConfig = {
		// 录音的时长，单位 ms，最大值 600000（10 分钟）
		duration: 600000,
		// 采样率
		sampleRate: 44100,
		// 录音通道数
		numberOfChannels: 1,
		// 编码码率
		encodeBitRate: 192000,
		// 音频格式，选择此格式创建的音频消息，可以在即时通信 IM 全平台（Android、iOS、微信小程序和Web）互通
		format: 'mp3',
	};

	const showAudio = () => {
		if (audioStatus.value) {
			// 显示语音输入按钮的逻辑
			audioStatus.value = false; // 设置为true，显示语音输入按钮
			initRecorder();
		} else {
			// 显示语音输入按钮的逻辑
			audioStatus.value = true; // 设置为true，显示语音输入按钮
			recorderManager = TUIGlobal?.getRecorderManager();
			recorderManager.onStart(onRecorderStart);
			recorderManager.onStop(onRecorderStop);
			recorderManager.onError(onRecorderError);
		}

	}
	const initRecorderView = () => {
		isRecording.value = false;
		touchBarText.value = '按住说话';
		modalText.value = '正在录音';
	}

	const initRecorderData = (options ?: { hasError : boolean }) => {
		clearInterval(recordTimer);
		recordTimer = undefined;
		recordTime = 0;
		firstTouchPageY = -1;
		isManualCancelBySlide = false;
		if (!options?.hasError) {
			recorderManager.stop();
		}
	}
	function initRecorder() {
		initRecorderData();
		initRecorderView();
	}
	const handleTouchStart = () => {
		if (isFingerTouchingScreen) {
			// 兼容 APP 首次由于用户授权产生的录音需要忽略
			isFirstAuthrizedRecord = true;
		}
	}
	const handleLongPress = () => {
		isFingerTouchingScreen = true;
		recorderManager.start(recordConfig);
	}
	const handleTouchMove = throttle((e) => {
		if (isRecording.value) {
			const pageY = e.changedTouches[e.changedTouches.length - 1].pageY;
			if (firstTouchPageY < 0) {
				firstTouchPageY = pageY;
			}
			const offset = (firstTouchPageY as number) - pageY;
			// 录音时的手势上划移动距离对应文案变化
			if (offset > 150) {
				touchBarText.value = '抬起取消';
				modalText.value = '松开手指 取消发送';
				isManualCancelBySlide = true;
			} else if (offset > 50) {
				touchBarText.value = '抬起发送';
				modalText.value = '继续上滑可取消';
				isManualCancelBySlide = false;
			} else {
				touchBarText.value = '抬起发送';
				modalText.value = '正在录音';
				isManualCancelBySlide = false;
			}
		}
	}, 100);
	// 手指离开页面滑动
	const handleTouchEnd = () => {
		isFingerTouchingScreen = false;
		recorderManager.stop();
	}
	const onRecorderStart = () => {
		if (!isFingerTouchingScreen) {
			// 如果开始录音但手指离开屏幕 说明是首次授权弹窗打断了录音 需要忽略
			isFirstAuthrizedRecord = true;
			recorderManager.stop();
			return;
		}
		recordTimer = setInterval(() => {
			recordTime += 1;
		}, 1000);
		touchBarText.value = '抬起发送';
		isRecording.value = true;
	}

	const onRecorderStop = (res : any) => {
		if (isFirstAuthrizedRecord) {
			// 兼容微信首次由于用户授权产生的录音需要忽略 对 APP 无效
			isFirstAuthrizedRecord = false;
			initRecorder();
			return;
		}
		if (isManualCancelBySlide || !isRecording.value) {
			initRecorder();
			return;
		}
		clearInterval(recordTimer);
		/**
		 * 兼容 uniapp 打包 app
		 * 兼容 uniapp 语音消息没有 duration
		 * duration 和 fileSize 需要用户自己补充
		 * 文件大小 = (音频码率) * 时间长度(单位:秒) / 8
		 * res.tempFilePath 存储录音文件的临时路径
		 */
		const tempFilePath = res.tempFilePath;
		const duration = res.duration ? res.duration : recordTime * 1000;
		const fileSize = res.fileSize ? res.fileSize : ((48 * recordTime) / 8) * 1024;

		if (duration < 1000) {
			uni.$wdToast.error('录音时间太短')
			// Toast({
			// 	message: '录音时间太短',
			// 	type: TOAST_TYPE.NORMAL,
			// 	duration: 1500,
			// });
		} else {
			uploadFile(tempFilePath).then((res) => {
				imStore.sendMessage({ file: { duration, tempFilePath, fileSize }, audioUrl: res.data.src }, 'audio', props.useruuid);
				emits('setScrollHeight')
			})


		}
		initRecorder();
	}

	const onRecorderError = () => {
		initRecorderData({ hasError: true });
		initRecorderView();
	}
	const setUploadShow = () => {
		emits('setUploadShow')
	}
	const sendMsg = () => {
		imStore.sendMessage({ text: msg.value }, 'text', props.useruuid);
		msg.value = '';
		emits('setScrollHeight')
	}
</script>
<style>
	.im-input-class {
		background: #f2f2f2;
	}
</style>
<style scoped lang="less">
	.input-box {
		display: flex;
		align-items: center;
		justify-content: space-between;
		background-color: #fff;
		height: 80rpx;
		padding: 24rpx;
		width: calc(100% - 24rpx - 24rpx);
		// position: fixed;
		// bottom: 0;

		.upload {
			width: 50rpx;
			padding-right: 20rpx;
		}

		.input {
			padding: 0 24rpx;
			width: 100%;

			// min-width: calc(100% - 50rpx - 24rpx - 137rpx - 24rpx);
		}

		.record-modal {
			height: 300rpx;
			width: 60vw;
			background-color: rgba(0, 0, 0, 0.8);
			position: fixed;
			left: 50%;
			top: 50%;
			transform: translate(-50%, -50%);
			z-index: 9999;
			border-radius: 24rpx;
			display: flex;
			flex-direction: column;
			overflow: hidden;

			.red-mask {
				position: absolute;
				inset: 0;
				background-color: rgba(#ff3e48, 0.5);
				opacity: 0;
				transition: opacity 10ms linear;
				z-index: 1;
			}

			.moving-slider {
				margin: 10vw;
				width: 40rpx;
				height: 16rpx;
				border-radius: 4rpx;
				background-color: #006fff;
				animation: loading 1s ease-in-out infinite alternate;
				z-index: 2;
			}

			.float-element {
				position: relative;
				z-index: 2;
			}
		}

		@keyframes loading {
			0% {
				transform: translate(0, 0);
			}

			100% {
				transform: translate(30vw, 0);
				background-color: #f5634a;
				width: 40px;
			}
		}

		.modal-title {
			text-align: center;
			color: #fff;
		}

		.audio-input {
			background: #f2f2f2;
			padding: 0 24rpx;
			margin: 0 24rpx;
			width: 100%;
			min-height: 60rpx;
			line-height: 60rpx;
			color: #999999;
			font-size: 28rpx;
			text-align: center;
			border-radius: 14rpx !important;
			padding: 0 24rpx !important;
		}

		.audio {
			min-width: 50rpx;
			height: 50rpx;
			border-radius: 50rpx;
			border: 2rpx solid #999999;
			display: flex;
			align-items: center;
			justify-content: center;

			text {
				color: #999999;
			}
		}




		.extra {
			min-width: 137rpx;
			height: 66rpx;
			text-align: center;
			line-height: 66rpx;
			background: #c91c1f;
			border-radius: 33rpx;

			font-family: PingFang;
			font-weight: 400;
			font-size: 28rpx;
			color: #ffffff;
		}
	}
</style>